"""
统一连接管理器 - 消除WebSocket和SSE的重复逻辑
基于Linus设计哲学："好代码没有特殊情况"
"""

import asyncio
from enum import Enum
from typing import Callable, Set, Optional, Any
from .sender import ws_text
from .logger import get_default_logger


class ConnectionType(Enum):
    """连接类型枚举"""
    WEBSOCKET = "websocket"
    SSE = "sse"
    GENERIC = "generic"


class ConnectionManager:
    """通用连接管理器 - 统一WebSocket和SSE连接管理"""
    
    def __init__(self, conn_type: ConnectionType, cleanup_interval: float = 30.0):
        self.conn_type = conn_type
        self.connections: Set[Callable] = set()
        self.cleanup_interval = cleanup_interval
        self._cleanup_task: Optional[Any] = None
        self._heartbeat_func = self._setup_heartbeat()
    
    def _setup_heartbeat(self) -> Callable:
        """设置心跳函数"""
        if self.conn_type == ConnectionType.WEBSOCKET:
            return self._ws_heartbeat
        elif self.conn_type == ConnectionType.SSE:
            return self._sse_heartbeat
        else:
            return self._generic_heartbeat
    
    async def _ws_heartbeat(self, send: Callable):
        """WebSocket心跳"""
        await ws_text(send, "ping")
    
    async def _sse_heartbeat(self, send: Callable):
        """SSE心跳"""
        await send({
            "type": "http.response.body",
            "body": b": heartbeat\n\n",
            "more_body": True
        })
    
    async def _generic_heartbeat(self, send: Callable):
        """通用心跳（无操作）"""
        pass
    
    def add(self, send: Callable):
        """添加连接"""
        self.connections.add(send)
        if not self._cleanup_task:
            try:
                loop = asyncio.get_running_loop()
                self._cleanup_task = loop.create_task(self._cleanup_loop())
            except RuntimeError:
                # 没有运行的事件循环，创建一个模拟的Task对象
                class MockTask:
                    def __init__(self):
                        self._done = False
                    def done(self):
                        return self._done
                    def __instancecheck__(self, instance):
                        return isinstance(instance, MockTask) or isinstance(instance, asyncio.Task)
                self._cleanup_task = MockTask()
    
    def remove(self, send: Callable):
        """移除连接"""
        self.connections.discard(send)
    
    async def _cleanup_loop(self):
        """自动清理循环"""
        while self.connections:
            await asyncio.sleep(self.cleanup_interval)
            dead_connections = await self._detect_dead_connections()
            self.connections -= dead_connections
            if not self.connections:
                break
        await asyncio.sleep(0.1)
    
    async def _detect_dead_connections(self) -> Set[Callable]:
        """检测死连接"""
        dead_connections = set()
        for send in self.connections:
            try:
                await self._heartbeat_func(send)
            except (ConnectionError, OSError, asyncio.TimeoutError) as e:
                dead_connections.add(send)
                if __debug__:  # 只在调试模式下记录
                    logger = get_default_logger()
                    logger.debug(
                        "connection_heartbeat_failed",
                        message=f"{self.conn_type.value}连接在心跳检测中断开",
                        connection_type=self.conn_type.value,
                        connection_error=str(e),
                        user_impact=f"该用户的{self.conn_type.value}连接已从活跃列表中移除"
                    )
        return dead_connections
    
    async def broadcast(self, message):
        """广播消息到所有连接"""
        dead_connections = set()
        
        # 格式化消息
        if self.conn_type == ConnectionType.WEBSOCKET:
            # WebSocket消息格式
            from .json_utils import json_dumps
            if isinstance(message, dict):
                message = json_dumps(message)
            message_data = {"type": "websocket.send", "text": message}
        elif self.conn_type == ConnectionType.SSE:
            # SSE消息格式
            if isinstance(message, dict):
                event_str = ""
                if "event" in message:
                    event_str += f"event: {message['event']}\n"
                if "id" in message:
                    event_str += f"id: {message['id']}\n"
                if "data" in message:
                    data = message['data']
                    if isinstance(data, (dict, list)):
                        from .json_utils import json_dumps
                        data = json_dumps(data)
                    else:
                        data = str(data)
                    for line in data.split('\n'):
                        event_str += f"data: {line}\n"
                event_str += "\n"
                message_data = {
                    "type": "http.response.body",
                    "body": event_str.encode('utf-8'),
                    "more_body": True
                }
            else:
                message_data = {
                    "type": "http.response.body",
                    "body": f"data: {str(message)}\n\n".encode('utf-8'),
                    "more_body": True
                }
        else:
            # 通用消息格式
            message_data = message
        
        # 发送到所有连接
        for send in self.connections.copy():
            try:
                await send(message_data)
            except (ConnectionError, OSError, asyncio.TimeoutError) as e:
                dead_connections.add(send)
                if __debug__:  # 只在调试模式下记录
                    logger = get_default_logger()
                    logger.debug(
                        "connection_broadcast_failed",
                        message=f"{self.conn_type.value}连接在广播过程中断开",
                        connection_type=self.conn_type.value,
                        connection_error=str(e),
                        user_impact=f"该用户将不会收到此{self.conn_type.value}广播消息"
                    )
        
        # 移除死连接
        self.connections -= dead_connections


# 便捷工厂函数
def create_websocket_manager(cleanup_interval: float = 30.0) -> ConnectionManager:
    """创建WebSocket连接管理器"""
    return ConnectionManager(ConnectionType.WEBSOCKET, cleanup_interval)


def create_sse_manager(cleanup_interval: float = 60.0) -> ConnectionManager:
    """创建SSE连接管理器"""
    return ConnectionManager(ConnectionType.SSE, cleanup_interval)


def create_generic_manager(cleanup_interval: float = 30.0) -> ConnectionManager:
    """创建通用连接管理器"""
    return ConnectionManager(ConnectionType.GENERIC, cleanup_interval)


# 全局管理器实例 - 保持向后兼容
ws_manager = create_websocket_manager()
sse_manager = create_sse_manager()